#pragma once
#include <dialects/Builtin/Dialect.h>
#include <dialects/Builtin/Types.h>
#include <lcir/IR/Prototype.h>

#include <optional>


namespace lcir::builtin::detail {
// Const原型，基本变量
template <class TypeTy, class ConstTy>
class ConstProto : public PrototypeCRTP<ConstProto<TypeTy, ConstTy>, BuiltinDialect> {
  ConstTy number;

 public:
  ConstProto(ConstTy number) : PrototypeCRTP<ConstProto<TypeTy, ConstTy>, BuiltinDialect>("ConstProto", TypeTy::get()) , number(number){}
  std::optional<std::string> getConstStr() const override { 
    std::stringstream ss;
    ss << number;
    return ss.str();
   }
   ConstTy getNumber() const { return number; }

};
// 变量的原型，支持Int32和Float
template <class TypeTy>
class VarProto : public PrototypeCRTP<VarProto<TypeTy>, BuiltinDialect> {
 public:
  VarProto() : PrototypeCRTP<VarProto<TypeTy>, BuiltinDialect>("VarProto", TypeTy::get()) {}
};
}  // namespace lcir::builtin::detail

namespace lcir::builtin {
using FloatVarProto = detail::VarProto<FloatType> ;
using Int32VarProto = detail::VarProto<Int32Type> ;
using BoolVarProto = detail::VarProto<BoolType> ;
using UnkownVarProto = detail::VarProto<UnkownType> ;

using FloatConstProto = detail::ConstProto<FloatType, float> ;
using Int32ConstProto = detail::ConstProto<Int32Type, int> ;
using BoolConstProto = detail::ConstProto<BoolType, bool> ;
class PointerVarProto : public PrototypeCRTP<Pointer, BuiltinDialect> {
 public:
 /**
  * @param ty 指针指向的类型
  */
  PointerVarProto(Type* ty) : PrototypeCRTP("PtrProto", Pointer::get(ty)) {}
};
}  // namespace lcir::builtin